"""
用户相关模型
"""
from sqlalchemy import Column, Integer, String, Boolean, DateTime,  ForeignKey
from sqlalchemy.orm import relationship
from passlib.context import CryptContext
from typing import List, Optional
from datetime import datetime, timedelta

from .base import Base, TimestampMixin, ActiveMixin
from core.logging_config import get_logger

logger = get_logger("user_model")

# 密码加密上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


# # 用户角色关联表
# user_role = Table(
#     'user_role',
#     Base.metadata,
#     Column('user_id', Integer, ForeignKey('user.id'), primary_key=True),
#     Column('role_id', Integer, ForeignKey('role.id'), primary_key=True)
# )


# # 角色权限关联表
# role_permission = Table(
#     'role_permission',
#     Base.metadata,
#     Column('role_id', Integer, ForeignKey('role.id'), primary_key=True),
#     Column('permission_id', Integer, ForeignKey('permission.id'), primary_key=True)
# )


class User(Base, ActiveMixin):
    """用户模型"""
    
    __tablename__ = "user"
    id = Column(Integer, primary_key=True, comment="用户ID")
    # 基本信息
    username = Column(String(50), unique=True, index=True, nullable=False, comment="用户名")
    email = Column(String(100), unique=True, index=True, nullable=False, comment="邮箱")
    password_hash = Column(String(255), nullable=False, comment="密码哈希")
    full_name = Column(String(100), comment="全名")
    phone = Column(String(20), comment="电话")
    avatar_url = Column(String(255), comment="头像URL")
    
    # 状态信息
    is_superuser = Column(Boolean, default=False, comment="是否超级用户")
    last_login = Column(DateTime, comment="最后登录时间")
    login_count = Column(Integer, default=0, comment="登录次数")
    role = Column(String(50), default="user", comment="角色")
    # 重置密码相关
    reset_token = Column(String(255), comment="重置密码令牌")
    reset_token_expires = Column(DateTime, comment="重置令牌过期时间")
    
    # 关系
    # roles = relationship("Role", secondary=user_role, back_populates="users")
    # data_sources = relationship("DataSource", back_populates="creator")
    # created_petitions = relationship("PetitionData", back_populates="creator")
    # created_tasks = relationship("AnalysisTask", back_populates="creator")
    # created_reports = relationship("Report", foreign_keys="Report.creator_id", back_populates="creator")
    
    def __init__(self, **kwargs):
        # 如果直接传入密码，进行哈希处理
        if 'password' in kwargs:
            kwargs['password_hash'] = self.get_password_hash(kwargs.pop('password'))
        super().__init__(**kwargs)
    
    def set_password(self, password: str):
        """设置密码"""
        self.password_hash = self.get_password_hash(password)
    
    def verify_password(self, password: str) -> bool:
        """验证密码"""
        return self.verify_password_hash(password, self.password_hash)
    
    @staticmethod
    def get_password_hash(password: str) -> str:
        """获取密码哈希"""
        return pwd_context.hash(password)
    
    @staticmethod
    def verify_password_hash(plain_password: str, hashed_password: str) -> bool:
        """验证密码哈希"""
        return pwd_context.verify(plain_password, hashed_password)
    
    def generate_reset_token(self) -> str:
        """生成重置密码令牌"""
        import secrets
        self.reset_token = secrets.token_urlsafe(32)
        self.reset_token_expires = datetime.utcnow() + timedelta(hours=1)
        return self.reset_token
    
    def is_reset_token_valid(self) -> bool:
        """检查重置令牌是否有效"""
        return (
            self.reset_token is not None and
            self.reset_token_expires is not None and
            self.reset_token_expires > datetime.utcnow()
        )
    
    def clear_reset_token(self):
        """清除重置令牌"""
        self.reset_token = None
        self.reset_token_expires = None
    
    def update_login_info(self):
        """更新登录信息"""
        self.last_login = datetime.utcnow()
        self.login_count += 1
    
    def has_permission(self, permission_code: str) -> bool:
        """检查用户是否有指定权限"""
        logger.info(f"DEBUG: has_permission called with permission_code={permission_code}")
        if self.is_superuser:
            return True

        # 临时处理：如果role是字符串，超级用户之外暂时都返回False
        # TODO: 实现完整的角色权限系统
        if isinstance(self.role, str):
            # 如果是admin角色，暂时返回True
            return self.role == "admin"

        # 检查用户角色是否有指定权限（用于未来的Role对象）
        if self.role and hasattr(self.role, 'has_permission'):
            return self.role.has_permission(permission_code)
        return False
    
    def get_role_names(self) -> List[str]:
        """获取用户角色名称列表"""
        if self.role:
            if isinstance(self.role, str):
                return [self.role]
            elif hasattr(self.role, 'name'):
                return [self.role.name]
        return []
    
    def get_permission_codes(self) -> List[str]:
        """获取用户权限代码列表"""
        if self.is_superuser:
            return ["*"]  # 超级用户拥有所有权限

        # 临时处理：如果role是字符串，admin角色返回所有权限
        if isinstance(self.role, str):
            if self.role == "admin":
                return ["*"]  # 管理员拥有所有权限
            return []  # 其他角色暂时没有权限

        permission_codes = set()
        if self.role and hasattr(self.role, 'get_permission_codes'):
            permission_codes.update(self.role.get_permission_codes())
        return list(permission_codes)
    
    def to_dict(self, exclude_password: bool = True) -> dict:
        """转换为字典"""
        result = super().to_dict()
        if exclude_password:
            result.pop('password_hash', None)
            result.pop('reset_token', None)
        
        # 添加角色信息
        # result['roles'] = [role.to_dict() for role in self.roles]
        # result['role_names'] = self.get_role_names()
        # result['permission_codes'] = self.get_permission_codes()

        return result

    @property
    def is_admin(self) -> bool:
        """是否管理员（is_superuser的别名，保持向后兼容）"""
        return self.is_superuser


# class Permission(Base, TimestampMixin):
#     """权限模型"""

#     __tablename__ = "permission"
#     id = Column(Integer, primary_key=True)
#     code = Column(String(50), unique=True, index=True, nullable=False, comment="权限代码")
#     name = Column(String(100), nullable=False, comment="权限名称")
#     description = Column(Text, comment="权限描述")
#     resource_type = Column(String(50), comment="资源类型")
#     action = Column(String(50), comment="操作类型")
#     parent_id = Column(Integer, ForeignKey('permission.id'), comment="父权限ID")

#     # 关系
#     # 一对多：一个父节点有多个子节点
#     children = relationship(
#         "Permission",
#         back_populates="parent",  # 反向引用到 parent
#         cascade="all, delete-orphan",  # 可选：删除父节点时级联删除子节点
#     )

#     # 多对一：多个子节点指向一个父节点 ← ✅ remote_side 必须放在这里！
#     parent = relationship(
#         "Permission",
#         back_populates="children",
#         remote_side=[id]  # ⚠️ 关键：id 是“上级”端，即“一”的那一侧
#     )
#     roles = relationship("Role", secondary=role_permission, back_populates="permissions")

#     def __init__(self, **kwargs):
#         """初始化权限"""
#         super().__init__(**kwargs)
#         # 确保权限代码格式统一
#         if self.code:
#             self.code = self.code.strip().lower()

#     def to_dict(self, include_children: bool = True, include_hierarchy: bool = False) -> dict:
#         """转换为字典"""
#         result = super().to_dict()

#         # 添加父权限信息
#         if self.parent:
#             result['parent_name'] = self.parent.name
#             result['parent_code'] = self.parent.code
#         else:
#             result['parent_name'] = None
#             result['parent_code'] = None

#         # 添加子权限信息
#         if include_children:
#             result['children'] = [child.to_dict(include_children=False) for child in self.children]
#             result['children_count'] = len(self.children)
#         else:
#             result['children_count'] = len(self.children)

#         # 添加层级信息
#         if include_hierarchy:
#             result['level'] = self.get_level()
#             result['path'] = self.get_path()
#             result['is_leaf'] = self.is_leaf()
#             result['is_root'] = self.is_root()

#         return result

#     def get_level(self) -> int:
#         """获取权限层级"""
#         if self.parent is None:
#             return 0
#         return self.parent.get_level() + 1

#     def get_path(self) -> str:
#         """获取权限路径"""
#         if self.parent is None:
#             return self.code
#         return f"{self.parent.get_path()}->{self.code}"

#     def is_root(self) -> bool:
#         """是否为根权限"""
#         return self.parent is None

#     def is_leaf(self) -> bool:
#         """是否为叶子权限"""
#         return len(self.children) == 0

#     def get_all_children(self) -> List['Permission']:
#         """获取所有子权限（递归）"""
#         children = []
#         for child in self.children:
#             children.append(child)
#             children.extend(child.get_all_children())
#         return children

#     def get_all_parent_codes(self) -> List[str]:
#         """获取所有父权限代码（递归）"""
#         codes = []
#         if self.parent:
#             codes.append(self.parent.code)
#             codes.extend(self.parent.get_all_parent_codes())
#         return codes

#     def has_child(self, permission_code: str) -> bool:
#         """检查是否包含指定子权限"""
#         for child in self.children:
#             if child.code == permission_code or child.has_child(permission_code):
#                 return True
#         return False

#     def is_descendant_of(self, permission_code: str) -> bool:
#         """检查是否为指定权限的后代"""
#         if self.parent is None:
#             return False
#         if self.parent.code == permission_code:
#             return True
#         return self.parent.is_descendant_of(permission_code)

#     def get_effective_permissions(self) -> List[str]:
#         """获取有效权限列表（包括所有父权限）"""
#         permissions = [self.code]
#         if self.parent:
#             permissions.extend(self.parent.get_effective_permissions())
#         return permissions

#     def matches_resource(self, resource_type: str = None, action: str = None) -> bool:
#         """检查权限是否匹配资源类型和操作"""
#         if resource_type and self.resource_type and self.resource_type != resource_type:
#             return False
#         if action and self.action and self.action != action:
#             return False
#         return True

#     def can_inherit_to(self, resource_type: str = None, action: str = None) -> bool:
#         """检查权限是否可以继承到指定资源和操作"""
#         # 如果没有指定资源类型和操作，则可以继承
#         if not resource_type and not action:
#             return True

#         # 如果权限没有定义资源类型和操作，则可以继承
#         if not self.resource_type and not self.action:
#             return True

#         # 检查匹配
#         return self.matches_resource(resource_type, action)

#     def get_full_name(self) -> str:
#         """获取权限全名（包含路径）"""
#         if self.parent:
#             return f"{self.parent.get_full_name()} > {self.name}"
#         return self.name

#     def get_description_with_context(self) -> str:
#         """获取带上下文的描述"""
#         desc = self.description or ""
#         if self.resource_type:
#             desc += f" (资源类型: {self.resource_type})"
#         if self.action:
#             desc += f" (操作: {self.action})"
#         return desc

#     def validate_hierarchy(self) -> List[str]:
#         """验证权限层级，返回错误信息列表"""
#         errors = []

#         # 检查循环引用
#         if self.parent and self.parent.is_descendant_of(self.code):
#             errors.append(f"权限 '{self.code}' 存在循环引用")

#         # 检查权限代码格式
#         if not self.code or not self.code.strip():
#             errors.append("权限代码不能为空")
#         elif not re.match(r'^[a-zA-Z_][a-zA-Z0-9_:]*$', self.code):
#             errors.append(f"权限代码 '{self.code}' 格式不正确")

#         # 检查必填字段
#         if not self.name or not self.name.strip():
#             errors.append("权限名称不能为空")

#         return errors

#     @classmethod
#     def get_root_permissions(cls, db: Session) -> List['Permission']:
#         """获取所有根权限"""
#         return db.query(cls).filter(cls.parent_id.is_(None)).all()

#     @classmethod
#     def get_permission_tree(cls, db: Session) -> List[dict]:
#         """获取权限树结构"""
#         roots = cls.get_root_permissions(db)
#         return [root.to_dict(include_hierarchy=True) for root in roots]

#     @classmethod
#     def find_by_code(cls, db: Session, code: str) -> Optional['Permission']:
#         """根据代码查找权限"""
#         return db.query(cls).filter(cls.code == code.strip().lower()).first()

#     @classmethod
#     def create_permission_hierarchy(cls, db: Session, permissions_data: List[dict]) -> List['Permission']:
#         """创建权限层级结构"""
#         created_permissions = []
#         permission_map = {}

#         # 首先创建所有权限
#         for perm_data in permissions_data:
#             permission = cls(**perm_data)
#             db.add(permission)
#             db.flush()  # 获取ID
#             permission_map[permission.code] = permission
#             created_permissions.append(permission)

#         # 然后建立父子关系
#         for perm_data in permissions_data:
#             permission = permission_map[perm_data['code']]
#             parent_code = perm_data.get('parent_code')
#             if parent_code and parent_code in permission_map:
#                 permission.parent_id = permission_map[parent_code].id

#         db.commit()
#         return created_permissions


# class Role(Base, TimestampMixin, ActiveMixin):
#     """角色模型"""
    
#     __tablename__ = "role"
    
#     name = Column(String(50), unique=True, index=True, nullable=False, comment="角色名称")
#     description = Column(Text, comment="角色描述")
#     sort_order = Column(Integer, default=0, comment="排序顺序")
    
#     # 关系
#     users = relationship("User", secondary=user_role, back_populates="roles")
#     permissions = relationship("Permission", secondary=role_permission, back_populates="roles")
    
#     def __init__(self, **kwargs):
#         """初始化角色"""
#         super().__init__(**kwargs)
#         # 确保角色名称格式统一
#         if self.name:
#             self.name = self.name.strip().lower()
    
#     def has_permission(self, permission_code: str) -> bool:
#         """检查角色是否有指定权限"""
#         # 直接匹配
#         if any(perm.code == permission_code for perm in self.permissions):
#             return True
        
#         # 检查是否有父权限
#         for perm in self.permissions:
#             if perm.has_child(permission_code):
#                 return True
        
#         return False
    
#     def has_any_permission(self, permission_codes: List[str]) -> bool:
#         """检查角色是否有任意一个指定权限"""
#         return any(self.has_permission(code) for code in permission_codes)
    
#     def has_all_permissions(self, permission_codes: List[str]) -> bool:
#         """检查角色是否有所有指定权限"""
#         return all(self.has_permission(code) for code in permission_codes)
    
#     def get_permission_codes(self) -> List[str]:
#         """获取角色权限代码列表"""
#         codes = set()
#         for perm in self.permissions:
#             codes.add(perm.code)
#             # 添加所有父权限
#             codes.update(perm.get_all_parent_codes())
#         return list(codes)
    
#     def get_effective_permissions(self) -> List[str]:
#         """获取有效权限列表（包括所有子权限）"""
#         permissions = set()
#         for perm in self.permissions:
#             permissions.add(perm.code)
#             # 添加所有子权限
#             for child in perm.get_all_children():
#                 permissions.add(child.code)
#         return list(permissions)
    
#     def get_permissions_by_resource(self, resource_type: str = None, action: str = None) -> List[Permission]:
#         """根据资源类型和操作获取权限"""
#         matching_permissions = []
#         for perm in self.permissions:
#             if perm.matches_resource(resource_type, action):
#                 matching_permissions.append(perm)
#         return matching_permissions
    
#     def add_permission(self, permission: 'Permission') -> None:
#         """添加权限"""
#         if permission not in self.permissions:
#             self.permissions.append(permission)
    
#     def remove_permission(self, permission: 'Permission') -> None:
#         """移除权限"""
#         if permission in self.permissions:
#             self.permissions.remove(permission)
    
#     def add_permission_by_code(self, db: Session, permission_code: str) -> bool:
#         """根据权限代码添加权限"""
#         permission = Permission.find_by_code(db, permission_code)
#         if permission:
#             self.add_permission(permission)
#             return True
#         return False
    
#     def remove_permission_by_code(self, permission_code: str) -> bool:
#         """根据权限代码移除权限"""
#         for perm in self.permissions:
#             if perm.code == permission_code:
#                 self.permissions.remove(perm)
#                 return True
#         return False
    
#     def get_user_count(self) -> int:
#         """获取拥有此角色的用户数量"""
#         return len(self.users)
    
#     def is_system_role(self) -> bool:
#         """是否为系统角色"""
#         return self.name in ['admin', 'manager', 'user']
    
#     def can_be_deleted(self) -> bool:
#         """是否可以被删除"""
#         # 系统角色不能删除
#         if self.is_system_role():
#             return False
        
#         # 如果有用户使用此角色，不能删除
#         if self.get_user_count() > 0:
#             return False
        
#         return True
    
#     def to_dict(self, include_permissions: bool = True, include_users: bool = False) -> dict:
#         """转换为字典"""
#         result = super().to_dict()
        
#         # 添加权限信息
#         if include_permissions:
#             result['permissions'] = [perm.to_dict(include_children=False) for perm in self.permissions]
#             result['permission_codes'] = self.get_permission_codes()
#             result['effective_permissions'] = self.get_effective_permissions()
#             result['permission_count'] = len(self.permissions)
#         else:
#             result['permission_count'] = len(self.permissions)
        
#         # 添加用户信息
#         if include_users:
#             result['users'] = [user.to_dict(exclude_password=True) for user in self.users]
#             result['user_count'] = self.get_user_count()
#         else:
#             result['user_count'] = self.get_user_count()
        
#         # 添加角色元信息
#         result['is_system_role'] = self.is_system_role()
#         result['can_be_deleted'] = self.can_be_deleted()
        
#         return result
    
#     def validate_permissions(self) -> List[str]:
#         """验证角色权限配置"""
#         errors = []
        
#         # 检查权限冲突
#         permission_codes = self.get_permission_codes()
#         if len(permission_codes) != len(set(permission_codes)):
#             errors.append("角色中存在重复权限")
        
#         # 检查权限层级冲突
#         for perm in self.permissions:
#             # 检查是否同时拥有父权限和子权限
#             for other_perm in self.permissions:
#                 if perm != other_perm:
#                     if perm.is_descendant_of(other_perm.code) or other_perm.is_descendant_of(perm.code):
#                         errors.append(f"权限 '{perm.code}' 与 '{other_perm.code}' 存在层级冲突")
        
#         return errors
    
#     @classmethod
#     def find_by_name(cls, db: Session, name: str) -> Optional['Role']:
#         """根据名称查找角色"""
#         return db.query(cls).filter(cls.name == name.strip().lower()).first()
    
#     @classmethod
#     def get_system_roles(cls, db: Session) -> List['Role']:
#         """获取系统角色"""
#         return db.query(cls).filter(cls.name.in_(['admin', 'manager', 'user'])).all()
    
#     @classmethod
#     def create_with_permissions(cls, db: Session, name: str, description: str = None, 
#                                permission_codes: List[str] = None) -> 'Role':
#         """创建角色并分配权限"""
#         role = cls(name=name, description=description)
#         db.add(role)
#         db.flush()
        
#         if permission_codes:
#             for code in permission_codes:
#                 permission = Permission.find_by_code(db, code)
#                 if permission:
#                     role.add_permission(permission)
        
#         db.commit()
#         return role


class UserSession(Base, TimestampMixin):
    """用户会话模型"""
    
    __tablename__ = "user_session"
    
    user_id = Column(Integer, ForeignKey('user.id'), nullable=False, comment="用户ID")
    session_token = Column(String(255), unique=True, index=True, nullable=False, comment="会话令牌")
    refresh_token = Column(String(255), unique=True, index=True, comment="刷新令牌")
    expires_at = Column(DateTime, nullable=False, comment="访问令牌过期时间")
    refresh_token_expires_at = Column(DateTime, comment="刷新令牌过期时间")
    is_active = Column(Boolean, default=True, comment="是否活跃")
    ip_address = Column(String(45), comment="IP地址")
    user_agent = Column(String(255), comment="用户代理")
    
    # 关系
    user = relationship("User", backref="sessions")
    
    def is_expired(self) -> bool:
        """检查会话是否过期"""
        return self.expires_at < datetime.utcnow()
    
    def is_refresh_token_expired(self) -> bool:
        """检查刷新令牌是否过期"""
        if not self.refresh_token_expires_at:
            return True
        return self.refresh_token_expires_at < datetime.utcnow()
    
    def is_valid(self) -> bool:
        """检查会话是否有效"""
        return self.is_active and not self.is_expired()
    
    def is_refresh_valid(self) -> bool:
        """检查刷新令牌是否有效"""
        return self.is_active and self.refresh_token and not self.is_refresh_token_expired()
    
    def expire(self):
        """使会话过期"""
        self.is_active = False
        self.expires_at = datetime.utcnow()